package com.yf.monitor.service;

import com.yf.monitor.ApiMonitorProperties;
import com.yf.monitor.entity.ApiRecord;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.jdbc.core.BatchPreparedStatementSetter;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

/**
 * @ClassName TDengineService
 * @Description TDengine服务实现
 * @Author Scott.Yin
 * @Date 2025/8/21 17:41
 * @Version 1.0
 **/
@Service
@Slf4j
public class TDengineService {

    private final JdbcTemplate jdbcTemplate;

    public TDengineService(ApiMonitorProperties properties) {
        // 创建TDengine数据源
        DriverManagerDataSource dataSource =
                new DriverManagerDataSource();
        dataSource.setDriverClassName("com.taosdata.jdbc.rs.RestfulDriver");
        dataSource.setUrl(properties.getTdengineUrl());
        dataSource.setUsername(properties.getTdengineUsername());
        dataSource.setPassword(properties.getTdenginePassword());
        this.jdbcTemplate = new JdbcTemplate(dataSource);
    }

    /**
     * 初始化数据库和表
     */
    @PostConstruct
    private void initDatabase() {
        try {
            // 创建数据库
            jdbcTemplate.execute("CREATE DATABASE IF NOT EXISTS apimonitor");
            jdbcTemplate.execute("USE apimonitor");

            // 创建超级表
            jdbcTemplate.execute("CREATE STABLE IF NOT EXISTS `api_records` (" +
                    "`ts` TIMESTAMP, " +
                    "`trace_id` NCHAR(64), " +
                    "`api_name` NCHAR(255), " +
                    "`method` NCHAR(10), " +
                    "`uri` NCHAR(500), " +
                    "`remote_addr` NCHAR(45), " +
                    "`user_agent` NCHAR(500), " +
                    "`request_body` NCHAR(4000), " +
                    "`response_body` NCHAR(4000), " +
                    "`success` BOOL, " +
                    "`error_msg` NCHAR(500), " +
                    "`error_stack` NCHAR(2000), " +
                    "`duration` INT, " +
                    "`keyword` NCHAR(45) " +
                    ") TAGS (`api_tag` NCHAR(50), `server_ip` NCHAR(50))");

            log.info("TDengine数据库初始化完成");
        } catch (Exception e) {
            log.error("TDengine数据库初始化失败", e);
        }
    }

    /**
     * 插入API记录
     */
    public void insertApiRecord(ApiRecord record) {
        try {
            String sql = String.format(
                    "INSERT INTO api_%s USING api_records TAGS('%s', '%s') VALUES (%d, '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', %b, '%s', '%s', %d, '%s')",
                    // 子表名: api_ + 接口名(简化处理)
                    normalizeTableName(record.getApiName()),
                    record.getApiName(),
                    record.getServerAddr(),
                    record.getTimestamp(),
                    record.getTraceId() != null ? record.getTraceId() : "",
                    record.getApiName(),
                    record.getMethod() != null ? record.getMethod() : "",
                    record.getUri() != null ? record.getUri() : "",
                    record.getRemoteAddr() != null ? record.getRemoteAddr() : "",
                    record.getUserAgent() != null ? record.getUserAgent() : "",
                    record.getRequestBody() != null ? StringUtils.truncate(record.getRequestBody(), 4000) : "",
                    record.getResponseBody() != null ? StringUtils.truncate(record.getResponseBody(), 4000) : "",
                    record.getSuccess(),
                    record.getErrorMsg() != null ? escapeSql(StringUtils.truncate(record.getErrorMsg(), 500)) : "",
                    record.getErrorStack() != null ? escapeSql(StringUtils.truncate(record.getErrorStack(), 2000)) : "",
                    record.getDuration(),
                    record.getKeyword() != null ? record.getKeyword() : ""
            );

            jdbcTemplate.execute(sql);
        } catch (Exception e) {
            log.error("插入API记录到TDengine失败", e);
        }
    }

    /**
     * 批量插入API记录
     **/
    public void insertBatchApiRecord(List<ApiRecord> recordList) {
        try {
            String sql = "INSERT INTO ? USING api_records TAGS(?, ?) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
            jdbcTemplate.batchUpdate(sql, new BatchPreparedStatementSetter() {
                @Override
                public void setValues(PreparedStatement ps, int i) throws SQLException {
                    ApiRecord record = recordList.get(i);
                    ps.setString(1, "api_" + normalizeTableName(record.getApiName()));
                    ps.setString(2, record.getApiName());
                    ps.setString(3, record.getServerAddr());
                    ps.setLong(4, record.getTimestamp());
                    ps.setString(5, record.getTraceId() != null ? record.getTraceId() : "");
                    ps.setString(6, record.getApiName());
                    ps.setString(7, record.getMethod() != null ? record.getMethod() : "");
                    ps.setString(8, record.getUri() != null ? record.getUri() : "");
                    ps.setString(9, record.getRemoteAddr() != null ? record.getRemoteAddr() : "");
                    ps.setString(10, record.getUserAgent() != null ? record.getUserAgent() : "");
                    if (record.getRequestBody() != null && record.getRequestBody().length() >= 4000) {
                        //超长内容直接丢弃
                        ps.setString(11, "");
                    } else {
                        ps.setString(11, record.getRequestBody() != null ? record.getRequestBody() : "");
                    }
                    if (record.getResponseBody() != null && record.getResponseBody().length() >= 4000) {
                        ps.setString(12, "");
                    } else {
                        ps.setString(12, record.getResponseBody() != null ? record.getResponseBody() : "");
                    }
                    ps.setBoolean(13, record.getSuccess());
                    ps.setString(14, record.getErrorMsg() != null ? escapeSql(StringUtils.truncate(record.getErrorMsg(), 500)) : "");
                    ps.setString(15, record.getErrorStack() != null ? escapeSql(StringUtils.truncate(record.getErrorStack(), 2000)) : "");
                    ps.setLong(16, record.getDuration());
                    ps.setString(17, record.getKeyword() != null ? record.getKeyword() : "");
                }

                @Override
                public int getBatchSize() {
                    return recordList.size();
                }
            });
        } catch (Exception e) {
            log.error("批量插入API记录到TDengine失败", e);
        }
    }

    /**
     * 查询API记录
     */
    public List<ApiRecord> queryApiRecords(String apiName, Long startTime, Long endTime,
                                           Integer limit, Integer offset) {
        List<ApiRecord> records = new ArrayList<>();

        try {
            StringBuilder sql = new StringBuilder(
                    "SELECT * FROM api_records WHERE 1=1");

            if (StringUtils.isNotBlank(apiName)) {
                sql.append(" AND api_tag = '").append(apiName).append("'");
            }

            if (startTime != null) {
                sql.append(" AND ts >= ").append(startTime);
            }

            if (endTime != null) {
                sql.append(" AND ts <= ").append(endTime);
            }

            sql.append(" ORDER BY ts DESC");

            if (limit != null) {
                sql.append(" LIMIT ").append(limit);
            }

            if (offset != null) {
                sql.append(" OFFSET ").append(offset);
            }

            jdbcTemplate.query(sql.toString(), rs -> {
                ApiRecord record = ApiRecord.builder()
                        .timestamp(rs.getLong("ts"))
                        .traceId(rs.getString("trace_id"))
                        .apiName(rs.getString("api_name"))
                        .method(rs.getString("method"))
                        .uri(rs.getString("uri"))
                        .remoteAddr(rs.getString("remote_addr"))
                        .userAgent(rs.getString("user_agent"))
                        .requestBody(rs.getString("request_body"))
                        .responseBody(rs.getString("response_body"))
                        .success(rs.getBoolean("success"))
                        .errorMsg(rs.getString("error_msg"))
                        .errorStack(rs.getString("error_stack"))
                        .duration(rs.getLong("duration"))
                        .build();

                records.add(record);
            });
        } catch (Exception e) {
            log.error("查询API记录失败", e);
        }

        return records;
    }

    /**
     * 获取接口统计信息
     */
//    public ApiStats getApiStats(String apiName, Long startTime, Long endTime) {
//        ApiStats stats = new ApiStats();
//
//        try {
//            String sql = String.format(
//                    "SELECT " +
//                            "COUNT(*) as total_count, " +
//                            "SUM(IF(success, 0, 1)) as error_count, " +
//                            "AVG(duration) as avg_duration, " +
//                            "MAX(duration) as max_duration, " +
//                            "PERCENTILE(duration, 95) as p95_duration " +
//                            "FROM api_records " +
//                            "WHERE api_tag = '%s' AND ts >= %d AND ts <= %d",
//                    apiName, startTime, endTime);
//
//            jdbcTemplate.query(sql, rs -> {
//                stats.setTotalCount(rs.getLong("total_count"));
//                stats.setErrorCount(rs.getLong("error_count"));
//                stats.setAvgDuration(rs.getDouble("avg_duration"));
//                stats.setMaxDuration(rs.getLong("max_duration"));
//                stats.setP95Duration(rs.getLong("p95_duration"));
//                stats.setSuccessRate(1.0 - (double)stats.getErrorCount() / stats.getTotalCount());
//            });
//        } catch (Exception e) {
//            log.error("获取接口统计信息失败", e);
//        }
//
//        return stats;
//    }

    /**
     * 规范化表名（TDengine表名限制）
     */
    private String normalizeTableName(String name) {
        if (name == null) return "unknown";
        // 移除特殊字符，只保留字母数字和下划线
        return name.replaceAll("[^a-zA-Z0-9_]", "_");
    }

    /**
     * SQL转义
     */
    private String escapeSql(String str) {
        return str.replace("'", "''");
    }
}
